/*
============================================================================
 Name        : nmsJpegTest.c
 Author      : Jian
 Version     :
 Copyright   : base on http://ce.sharif.edu/~ahmadinejad/jpeg/
 Description : nmsJpegTest.c - source file
============================================================================
*/

/* INCLUDE FILES */

#include "nmsJpegTest.h"
#include "nmsJpeg.h"
#include "nmsJpegDct.h"
#include "nmsJpegMcuReader.h"
#include "nmsFrame.h"

#ifdef __NMS_JPEG_DEBUG

#define __abs(c) ((c) >= 0 ? (c) : -(c))

extern nmsRgbMatrix nmsRgbCache ;


/*
*  A tiny/limited debug memory checker for test
*/

#define __CHECKER_MAX_ENTRY 150

typedef struct __nms_checker_entry {
    void*  ptr ;
    UINT32 size ;
    char   mallocInfo[60] ;
} nmsCheckerEntry;

typedef struct __nms_memory_checker {
    nmsCheckerEntry entrys[__CHECKER_MAX_ENTRY] ;
    int             entryCount ;
    int             memCrest ;
    int             curMemUsage ;
} nmsMemChecker;

static nmsMemChecker* _memChecker = NULL ;

void* nmsDebugMalloc(UINT32 size, const char* fileName, int line)
{
    void* ptr   = nmsMallocL(size) ;

    const char* rFileName = NULL ;

    if (!_memChecker) {
        _memChecker = (nmsMemChecker*)nmsMallocL(sizeof(nmsMemChecker)) ;
        nmsMemSet(_memChecker, 0, sizeof(nmsMemChecker)) ;
    }

    __NMS_ASSERT_DEFENSE(_memChecker->entryCount < __CHECKER_MAX_ENTRY, return ptr) ;

    rFileName = strrchr(fileName, '\\') ;
    if (!rFileName) rFileName = fileName ;

    _memChecker->entrys[_memChecker->entryCount].ptr  = ptr ;
    _memChecker->entrys[_memChecker->entryCount].size = size ;
    sprintf(_memChecker->entrys[_memChecker->entryCount].mallocInfo, "File: %s, line: %d, malloc size: %d", rFileName, line, size) ;

    _memChecker->curMemUsage += size ;
    if (_memChecker->curMemUsage > _memChecker->memCrest)
        _memChecker->memCrest = _memChecker->curMemUsage ;

    _memChecker->entryCount++ ;

    return ptr ;
}

void nmsDebugFree(void* ptr)
{
    int i = 0 ;

    nmsFreeL(ptr) ;

    __NMS_ASSERT_DEFENSE(_memChecker, return) ;

    for (; i < _memChecker->entryCount; i++) {
        if (_memChecker->entrys[i].ptr == ptr) {
            _memChecker->curMemUsage -= _memChecker->entrys[i].size;
            memmove(&(_memChecker->entrys[i]), &(_memChecker->entrys[i + 1]), (_memChecker->entryCount - i - 1) * sizeof(nmsCheckerEntry)) ;
            _memChecker->entryCount-- ;
            return ;
        }
    }

    __NMS_ASSERT(0) ;
}

/*
* bmp dumper
* warning: just for test only , this dumper will use lots of memory .
*/

typedef struct __bmp_rgb {
    UINT8 b ;
    UINT8 g ;
    UINT8 r ;
} BmpRgb;


typedef struct __bmp_dumer {
    BmpRgb*  rgbArray ;
    nmsJpeg* jpg ;
    int      mcuLen ;
    int      width ;
    HFILE    file ;
} BmpDumer;

BmpDumer* nmsBmpDumperCreate(nmsJpeg* jpg, const WCHAR* bmpName)
{
    int bmtWidth, bmpHeight, fileSize;
    int dummy = 0 ;
    BmpDumer* dumper = (BmpDumer*)nmsMallocL(sizeof(BmpDumer)) ;

    unsigned char header[54] = {
        0x42, 0x4d, 0, 0, 0, 0, 0, 0, 0, 0,
        54, 0, 0, 0, 40, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 1, 0, 24, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0
    };

    dumper->jpg = jpg ;

    bmtWidth  = jpg->frame->width ;
    if (bmtWidth % 4 != 0)
        bmtWidth += (4 - jpg->frame->width % 4) ;

    bmpHeight = jpg->frame->height ;

    fileSize = bmtWidth * bmpHeight * 3 + 54;

    header[2] = (unsigned char)(fileSize &0x000000ff);
    header[3] = (fileSize >> 8) & 0x000000ff;
    header[4] = (fileSize >> 16) & 0x000000ff;
    header[5] = (fileSize >> 24) & 0x000000ff;

    header[18] = bmtWidth & 0x000000ff;
    header[19] = (bmtWidth >> 8) &0x000000ff;
    header[20] = (bmtWidth >> 16) &0x000000ff;
    header[21] = (bmtWidth >> 24) &0x000000ff;

    bmpHeight = -bmpHeight ;
    header[22] = bmpHeight & 0x000000ff;
    header[23] = (bmpHeight >> 8) &0x000000ff;
    header[24] = (bmpHeight >> 16) &0x000000ff;
    header[25] = (bmpHeight >> 24) &0x000000ff;

    dumper->mcuLen = jpg->mcuWidth ;
    dumper->width  = bmtWidth ;

    dumper->rgbArray = (BmpRgb*)nmsMallocL(bmtWidth * sizeof(BmpRgb) * dumper->mcuLen) ;
    nmsMemSet(dumper->rgbArray, 0, bmtWidth * sizeof(BmpRgb) * dumper->mcuLen) ;

    dumper->file = nmsFsOpenW((WCHAR*)bmpName, NMS_FS_CREATE_ALWAYS) ;

    nmsFsWrite(dumper->file, header, 54, &dummy) ;

    return dumper ;
}

void nmsBmpDumperDump(BmpDumer* dumper, int mcuIndex)
{
    int i = 0 ;
    int j = 0 ;
    int rgb = 0 ;

    BmpRgb* pRgb = dumper->rgbArray + mcuIndex * dumper->mcuLen;

    int loopWidth = dumper->mcuLen ;
    if (mcuIndex == dumper->jpg->mcuPerLine - 1 && (dumper->width % dumper->mcuLen != 0)) {
        loopWidth = dumper->width % dumper->mcuLen ;
    }

    for (i = 0; i < dumper->mcuLen; i++) {
        for (j = 0; j < loopWidth; j++) {
            BmpRgb* tRgb = pRgb + j ;
            rgb = nmsJpegGetRgb(&nmsRgbCache, j, i) ;
            tRgb->r = __getR(rgb) ;
            tRgb->g = __getG(rgb) ;
            tRgb->b = __getB(rgb) ;
        }
        pRgb += dumper->width ;
    }

    if (mcuIndex == dumper->jpg->mcuPerLine - 1) {
        int dummy = 0 ;
        nmsFsWrite(dumper->file, dumper->rgbArray, dumper->width * sizeof(BmpRgb) * dumper->mcuLen, &dummy) ;
    }
}


void nmsBmpDumperDestroy(BmpDumer* dumper)
{
    if (dumper) {
        if (dumper->file)  nmsFsClose(dumper->file) ;
        nmsFreeL(dumper->rgbArray) ;
        nmsFreeL(dumper) ;
    }
}


static int _testZigZag()
{
    const int testTime = 50 ;
    int testData[64]  = {0};
    int coverData[64] = {0} ;
    int i = 0 ;

    for (i = 0; i < testTime; i++) {
        int j = 0 ;
        for (j = 0; j < 64; j++) {
            testData[j]  = nmsRandom() ;
            coverData[j] = testData[j] ;
        }

        nmsJpegFromZigZag4(coverData) ;
        nmsJpegToZiZag(coverData) ;

        for (j = 0; j < 64; j++) {
            if (testData[j] != coverData[j]) {
                nprintf("_testZigZag %d != %d", testData[j], coverData[j]) ;
                return -1 ;
            }
        }
    }

    return 0 ;
}

static int _testDct()
{
    int ret = 0 ;

    const int ori[8][8] = {
        0, 17, 222, 65535,1000, 9999, 1111, 30,
        0,0,0,0,0,0,0,0,
        1, 2, 3, 4, 5 , 6 , 7, 8,
        111, 222, 333, 444, 555, 666,777,888,
        65535,65535,65535,65535,65535,65535,65535,65535,
        876,989,8766,7867,122,1222,32424,45345,
        567,5677,35434,2434,23478,9982,989,532,
        8767,2356,123,12321,984,276,8768,23276
    } ;

    const int _dctVri[8][8] = {
        1023, -1023, -1023, -1023, 1023, 1023, -86, -1023,
        -1023, 1023, -1023, 1023, 1023, 1023, -1023, -1023,
        -1023, 1023, -1023, -1023, 1023, 1023, -1023, -1023,
        1023, -1023, -1023, -1023, 1023, 1023, -1023, -1023,
        1023, 1023, -1023, 1023, 1023, 1023, -1023, -1023,
        -1023, 1023, -1023, -1023, -1023, 1023, 1023, 870,
        -1023, -1023, 1023, -1023, 1023, 1023, -1023, -1023,
        1023, 1023, -1023, 1023, -1023, -1023, 1023, 955
    } ;


    const int _idctVri[8][8] = {
        -223, -752, -1050, 4287, -315, -1060, -164, -1304,
        -59, 15, -1056, 657, 297, 59, -242, 243,
        -132, -426, 276, -1101, -388, 130, -364, -80,
        288, -563, 295, 311, -267, 226, 231, -293,
        732, 698, 232, 694, 1922, 1990, 672, 706,
        -1326, -839, -841, 1249, -1036, -759, 1258, 2815,
        -851, -282, 2848, -536, 352, 567, -344, -102,
        133, 173, -568, 1014, -279, -406, 47, 779
    } ;

    int dctData[8][8] = {0};
    int idctData[8][8] = {0};

    int i = 0 ;
    int j = 0 ;

    nmsJpegDct(ori, dctData) ;

    for (i = 0; i < 8; i++) {
        for (j = 0; j < 8; j++) {
            if (__abs(dctData[i][j] - _dctVri[i][j]) > 1) {
                nprintf("_testDct DCT error: In row = %d, column = %d dctData = %d not equal to _dctVri = %d", i, j, dctData[i][j], _dctVri[i][j]) ;
                ret = -1 ;
            }
        }
    }

    nmsJpegIdct(dctData, idctData) ;

    for (i = 0; i < 8; i++) {
        for (j = 0; j < 8; j++) {
            if (__abs(idctData[i][j] - _idctVri[i][j]) > 1) {
                nprintf("_testDct IDCT error: In row = %d, column = %d idctData = %d not equal to _idctVri = %d", i, j, idctData[i][j], _idctVri[i][j]) ;
                ret = -1 ;
            }
        }
    }

    return ret ;
}

static int _testDcAcVal()
{
    int val;
    int tmpVal ;
    int sVal   = 0 ;
    int dVal   = 0 ;
    int bitLen = 0 ;

    for (val = -2047; val <= 2047; val++) {
        bitLen = 10 ;

        tmpVal = __abs(val) ;
        for (; bitLen >= 0; bitLen--) {
            if (tmpVal & (1 << bitLen))
                break ;
        }

        bitLen += 1 ;

        if (bitLen == 0) {
            if (val != 0) {
                nprintf("_testDcAcVal error bit = 0 val = %d", val) ;
                return -1 ;
            }

            continue ;
        }

        sVal = (1 << (bitLen - 1)) ;

        if (val >= 0)
            dVal = sVal + (tmpVal - sVal);
        else
            dVal = sVal - (tmpVal - sVal + 1);

        {
            /* check */
            int checkVal = dVal ;
            if (!(checkVal & (1<< (bitLen-1)))) {
                checkVal|=(-(1<<(bitLen)));
                checkVal++;
            }

            if (checkVal != val) {
                nprintf("_testDcAcVal check error checkVal %d != val %d, dVal = %d, sVal = %d, bitLen = %d", checkVal, val, dVal, sVal,bitLen) ;
                return -1 ;
            }
        }
    }

    return 0 ;
}

static int _testHuffman()
{
    int ret = -1 ;
    int rgb[256] = {0} ;
    nmsJpegMcu* mcu = NULL ;
    nmsJpeg* jpg    = NULL ;
    HFILE tFile     = 0 ;
    int tFileSize   = 0 ;
    int i, j, k, l, m;
    int preDc[__NMC_JPEG_COMP_ID_CR + 1] = {0} ;

    nmsMatrix oriMatrix, dqtMatrix, idctMatrix, fileMatrix ;
    UINT32 fileBit = 0 ;

    nmsFsGetFileSizeWithNameW((WCHAR*)L"c:\\data\\testHuffman.dat", &tFileSize) ;

    tFile = nmsFsOpenW((WCHAR*)L"c:\\data\\testHuffman.dat", NMS_FS_READ) ;
    if (tFile == 0) {
        nprintf("_testHuffman testHuffman.dat can not open") ;
        goto _exit ;
    }

    jpg = nmsJpegOpen((const WCHAR*)L"c:\\data\\testHuffman.jpg") ;
    if (!jpg) {
        nprintf("_testHuffman nmsJpegOpen error") ;
        goto _exit ;
    }

    mcu = nmsMcuCreate(jpg) ;
    nmsMcuInit(mcu, jpg->imgDataPos * 8, 0, preDc, NULL) ;

    for (i = 0; i < jpg->mcuLine; i++) {
        for (j =0; j < jpg->mcuPerLine; j++) {
            for (k = __NMC_JPEG_COMP_ID_Y; k <= __NMC_JPEG_COMP_ID_CR; k++) {
                for (l = 0; l < jpg->frame->comp[k].duCount; l++) {

                    if (nmsMcuTestReadDU(mcu, k, &oriMatrix, &dqtMatrix, &idctMatrix)) {
                        nprintf("_testHuffman read du error") ;
                        goto _exit ;
                    }

                    nmsMcuTestCheckMaker(mcu) ;

                    nmsJpegReadFile(tFile, fileMatrix, 64 * 4) ;
                    for (m = 0 ; m < 64; m++) {
                        if (oriMatrix[m] != fileMatrix[m]) {
                            nprintf("_testHuffman error oriMatrix in %d : %d != %d", m, oriMatrix[m], fileMatrix[m]) ;
                            goto _exit ;
                        }
                    }

                    nmsJpegReadFile(tFile, fileMatrix, 64 * 4) ;
                    for (m = 0 ; m < 64; m++) {
                        if (dqtMatrix[m] != fileMatrix[m]) {
                            nprintf("_testHuffman error dqtMatrix in %d : %d != %d", m, dqtMatrix[m], fileMatrix[m]) ;
                            goto _exit ;
                        }
                    }

                    nmsJpegReadFile(tFile, fileMatrix, 64 * 4) ;
                    for (m = 0 ; m < 64; m++) {
                        if (__abs(idctMatrix[m] - fileMatrix[m]) > 1) {
                            // if (idctMatrix[m] != fileMatrix[m]) {
                            nprintf("_testHuffman error idctMatrix in %d : %d != %d", m, idctMatrix[m], fileMatrix[m]) ;
                            goto _exit ;
                        }
                    }

                    nmsJpegReadFile(tFile, &fileBit, 4) ;
                    if (mcu->testReadBitTotal != fileBit) {
                        nprintf("_testHuffman error testReadBitTotal = %d != fileBit = %d", mcu->testReadBitTotal, fileBit) ;
                        goto _exit ;
                    }
                }
            }
        }
    }

    if (nmsFsTell(tFile) != tFileSize) {
        nprintf("_testHuffman error did not read all testHuffman.dat data pos = %d, size = %d", nmsFsTell(tFile), tFileSize) ;
        goto _exit ;
    }

    ret = 0 ;

_exit:

    if (tFile) nmsFsClose(tFile) ;
    if (jpg)   nmsJpegClose(jpg) ;
    if (mcu)   nmsMcuDesctroy(mcu) ;

    return ret ;
}

#define  __TEST_DUMP_BMP

static int _testToRgb()
{
    int ret           = -1 ;
    nmsJpegMcu* mcu   = NULL ;
    nmsJpeg* jpg      = NULL ;
    int i, j ;
    int mcuWidth , mcuHeight, lineWidth;
    int preDc[__NMC_JPEG_COMP_ID_CR + 1] = {0} ;

    UINT32 tmpRgbLine[16] = {0} ;
    HFILE tFile           = 0 ;
    int tFileSize         = 0 ;

    BmpDumer* bmpDumper   = NULL ;

    nmsFsGetFileSizeWithNameW((WCHAR*)L"c:\\data\\testRgb.dat", &tFileSize) ;

    tFile = nmsFsOpenW((WCHAR*)L"c:\\data\\testRgb.dat", NMS_FS_READ) ;
    if (tFile == 0) {
        nprintf("_testToRgb testHuffman.dat can not open") ;
        goto _exit ;
    }

    jpg = nmsJpegOpen((const WCHAR*)L"c:\\data\\test.jpg") ;
    if (!jpg) {
        nprintf("_testToRgb nmsJpegOpen error") ;
        goto _exit ;
    }

#ifdef __TEST_DUMP_BMP
    bmpDumper = nmsBmpDumperCreate(jpg, L"c:\\data\\dump.bmp") ;
#endif

    nmsMcuInitCbCrIndexArray(jpg) ;

    mcu = nmsMcuCreate(jpg) ;
    nmsMcuInit(mcu, jpg->imgDataPos * 8, 0, preDc, NULL) ;

    mcuWidth  = jpg->mcuWidth;
    mcuHeight = jpg->mcuHeight ;
    lineWidth = jpg->frame->width * 4 ;


    for (i = 0; i < jpg->mcuLine; i++) {
        for (j =0; j < jpg->mcuPerLine; j++) {
            int k = 0 ;
            int m = 0 ;
            int startPos = j * mcuWidth * 4 + lineWidth * i * mcuHeight ;
            int loopHeight = mcuHeight ;
            int loopWidth  = mcuWidth ;

            if (nmsMcuReadNext(mcu) < 0) {
                nprintf("_testToRgb nmsMcuReadNext error i = %d, j = %d", i, j) ;
                goto _exit ;
            }

            if (j == jpg->mcuPerLine - 1) {
                loopWidth = jpg->frame->width % mcuWidth ;
                loopWidth = (loopWidth == 0) ? mcuWidth : loopWidth ;
            }

            if (i == jpg->mcuLine - 1) {
                loopHeight = jpg->frame->height % mcuHeight ;
                loopHeight = (loopHeight == 0) ? mcuHeight : loopHeight ;
            }

            for (k = 0; k < loopHeight; k++) {
                UINT32 rgb = 0 ;
                nmsFsSeek(tFile, startPos, NMS_FS_FILE_BEGIN) ;
                nmsJpegReadFile(tFile, tmpRgbLine, mcuWidth * 4) ;
                startPos += lineWidth ;

                for (m = 0; m < loopWidth; m++) {
                    rgb = nmsJpegGetRgb(&nmsRgbCache, m, k) ;
                    if (__abs(__getR(rgb) - __getR(tmpRgbLine[m])) > 2) {
                        nprintf("_testToRgb rgb[%d][%d]: get red %d != %d", k, m, __getR(rgb), __getR(tmpRgbLine[m])) ;
                        goto _exit ;
                    }
                    if (__abs(__getG(rgb) - __getG(tmpRgbLine[m]))> 2) {
                        nprintf("_testToRgb rgb[%d][%d]: get green %d != %d", k, m, __getG(rgb), __getG(tmpRgbLine[m])) ;
                        goto _exit ;
                    }
                    if (__abs(__getB(rgb) - __getB(tmpRgbLine[m])) > 2) {
                        nprintf("_testToRgb rgb[%d][%d]: get blue %d != %d", k, m, __getB(rgb), __getB(tmpRgbLine[m])) ;
                        goto _exit ;
                    }
                }
            }

#ifdef __TEST_DUMP_BMP
            nmsBmpDumperDump(bmpDumper, j) ;
#endif

        }
    }

    if (nmsFsTell(tFile) != tFileSize) {
        nprintf("_testToRgb error did not read all testRgb.dat data pos = %d, size = %d", nmsFsTell(tFile), tFileSize) ;
        goto _exit ;
    }

    ret = 0 ;

_exit:

    if (mcu)       nmsMcuDesctroy(mcu) ;
    if (jpg)       nmsJpegClose(jpg) ;
    if (tFile)     nmsFsClose(tFile) ;
    if (bmpDumper) nmsBmpDumperDestroy(bmpDumper) ;

    return ret ;
}

static int _testCompressQt()
{
    int ret = -1 ;
    nmsJpeg* jpg = NULL ;
    int duData[64]   = {0} ;
    int fileData[64] = {0} ;
    int i = 0 ;
    int j = 0 ;

    HFILE tFile = nmsFsOpenW((WCHAR*)L"c:\\data\\testCompressQT.dat", NMS_FS_READ) ;

    if (tFile == 0) {
        nprintf("_testCompressQt testCompressQT.dat can not open") ;
        goto _exit ;
    }

    jpg = nmsJpegOpen((const WCHAR*)L"c:\\data\\test.jpg") ;
    if (!jpg) {
        nprintf("_testCompressQt nmsJpegOpen error") ;
        goto _exit ;
    }

    for (i = 0; i < 4; i++) {

        nmsJpegTestReadDu(jpg, __NMC_JPEG_COMP_ID_Y,  i, duData) ;
        nmsJpegReadFile(tFile, fileData, 64 *4) ;

        for (j = 0; j < 64; j++) {
            if (__abs(duData[j] - fileData[j]) > 0) {
                nprintf("_testCompressQt in __NMC_JPEG_COMP_ID_Y %d, %d, %d = %d", i, j, duData[j], fileData[j]) ;
                goto _exit ;
            }
        }

    }

    nmsJpegTestReadDu(jpg, __NMC_JPEG_COMP_ID_CB,  0, duData) ;
    nmsJpegReadFile(tFile, fileData, 64 *4) ;

    for (j = 0; j < 64; j++) {
        if (__abs(duData[j] - fileData[j]) > 0) {
            nprintf("_testCompressQt in __NMC_JPEG_COMP_ID_CB  %d, %d = %d", j, duData[j], fileData[j]) ;
            goto _exit ;
        }
    }

    nmsJpegTestReadDu(jpg, __NMC_JPEG_COMP_ID_CR,  0, duData) ;
    nmsJpegReadFile(tFile, fileData, 64 *4) ;

    for (j = 0; j < 64; j++) {
        if (__abs(duData[j] - fileData[j]) > 0) {
            nprintf("_testCompressQt in __NMC_JPEG_COMP_ID_CR %d, %d = %d", j, duData[j], fileData[j]) ;
            goto _exit ;
        }
    }

    ret = 0 ;

_exit:

    if (jpg)   nmsJpegClose(jpg) ;
    if (tFile) nmsFsClose(tFile) ;

    return ret ;
}

static int _testReadCompressJPGQT()
{
    int ret = -1 ;
    int rgb[256] = {0} ;
    nmsJpegMcu* mcu = NULL ;
    nmsJpeg* jpg    = NULL ;
    HFILE tFile     = 0 ;
    int i, k, m;
    int preDc[__NMC_JPEG_COMP_ID_CR + 1] = {0} ;

    nmsMatrix oriMatrix, dqtMatrix, idctMatrix, fileMatrix ;
    UINT32 fileBit = 0 ;

    tFile = nmsFsOpenW((WCHAR*)L"c:\\data\\testCompressQT.dat", NMS_FS_READ) ;
    if (tFile == 0) {
        nprintf("_testDummy testCompressQT.dat can not open") ;
        goto _exit ;
    }

    jpg = nmsJpegOpen((const WCHAR*)L"c:\\data\\testCompress.jpg") ;
    if (!jpg) {
        nprintf("_testDummy nmsJpegOpen error") ;
        goto _exit ;
    }

    mcu = nmsMcuCreate(jpg) ;
    nmsMcuInit(mcu, jpg->imgDataPos * 8, 0, preDc, NULL) ;

    for (i = 0; i < 6; i++) {
        if (i < 4) k = 1 ;
        else if (i == 4) k = 2 ;
        else if (i == 5) k = 3 ;

        if (nmsMcuTestReadDU(mcu, k, &oriMatrix, &dqtMatrix, &idctMatrix)) {
            nprintf("_testDummy read du error") ;
            goto _exit ;
        }

        nmsMcuTestCheckMaker(mcu) ;

        nmsJpegReadFile(tFile, fileMatrix, 64 * 4) ;
        for (m = 0 ; m < 64; m++) {
            if (oriMatrix[m] != fileMatrix[m]) {
                nprintf("_testDummy error dqtMatrix in %d %d : %d != %d", i, m, dqtMatrix[m], fileMatrix[m]) ;
                goto _exit ;
            }
        }
    }

    ret = 0 ;

_exit:

    if (tFile) nmsFsClose(tFile) ;
    if (jpg)   nmsJpegClose(jpg) ;
    if (mcu)   nmsMcuDesctroy(mcu) ;

    return ret ;
}

static int _testJpegCompress(int scale)
{
    int ret = -1 ;

    nmsJpeg* jpg = nmsJpegOpen((const WCHAR*)L"c:\\data\\test.jpg") ;

    if (!jpg) {
        nprintf("_testJpegCompress nmsJpegOpen error") ;
        goto _exit ;
    }

    if (nmsJpegSave(jpg, (const WCHAR*)L"c:\\data\\testCompress.jpg", scale) < 0) {
        nprintf("_testJpegCompress scale = %d, nmsJpegSave error", scale) ;
        goto _exit ;
    }

    ret = 0 ;

_exit:

    if (jpg)  nmsJpegClose(jpg) ;

    return ret ;
}



static UINT32 _useTime = 0 ;

int nmsJpegTest()
{
    UINT32 startTime = nmsGetSystemTime() ;

    if (_memChecker) {
        nmsFreeL(_memChecker) ;
        _memChecker = NULL ;
    }

    _useTime = 0 ;

    nprintf("=============== Start a New JPEG Test ===============") ;

    // if (_testZigZag() < 0) return -1 ;

    // if (_testDcAcVal() < 0) return -1 ;

    // if (_testDct() < 0)  return -1 ;

    // if (_testHuffman() < 0)  return -1 ;

    // if (_testToRgb() < 0)  return -1 ;

    // if (_testCompressQt() < 0) return -1 ;

    // if (_testReadCompressJPGQT() < 0) return -1 ;

    if (_testJpegCompress(100) < 0) return -1 ;

    _useTime = nmsGetSystemTime() - startTime ;

    nprintf("Jpeg Test SUCCEED and _useTime = %d", _useTime) ;

    if (_memChecker) {
        if (_memChecker->entryCount != 0) {
            int i = 0 ;
            nprintf("Memory crest = %d and got %d memroy leak below", _memChecker->memCrest, _memChecker->entryCount) ;
            for (; i < _memChecker->entryCount; i++)
                nprintf("%s", _memChecker->entrys[i].mallocInfo) ;
        } else {
            nprintf("Memory crest = %d and no memroy leak", _memChecker->memCrest) ;
        }
    }

    nprintf("=============== Jpeg Test END ===============") ;

    return 0 ;
}

UINT32 nmsJpegTestGetLastTime()
{
    return _useTime ;
}

#endif  /* __NMS_JPEG_DEBUG */

/* End of File */
